import { Callout } from "nextra-theme-docs";

# appsettings.json 配置

`appsettings.json` 文件是 GZCTF 的核心配置文件，通过挂载入容器内的方式进行配置。本篇将介绍配置文件的各个字段的含义。

<Callout type="info">

`appsettings.json` 的每次更新都需要重启 GZCTF 服务才能生效。

</Callout>

## 配置文件结构

此处给出一个完整的配置文件示例：

```json
{
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "Database": "Host=db:5432;Database=gzctf;Username=postgres;Password=<Database Password>"
    // redis is optional
    //"RedisCache": "cache:6379,password=<Redis Password>"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Loki": {
      "Enable": true,
      "EndpointUri": "http://loki:3100",
      "Labels": [
        {
          "Key": "app",
          "Value": "gzctf"
        }
      ],
      "PropertiesAsLabels": ["app"],
      "Credentials": {
        "Login": "login",
        "Password": "password"
      },
      "Tenant": "my-tenant",
      "MinimumLevel": "Trace"
    }
  },
  "Telemetry": {
    "Prometheus": {
      "Enable": false,
      "Port": 3000,
      "TotalNameSuffixForCounters": false
    },
    "OpenTelemetry": {
      "Enable": false,
      "Protocol": "Grpc",
      "EndpointUri": "http://jaeger-collector:4317"
    },
    "AzureMonitor": {
      "Enable": false,
      "ConnectionString": "InstrumentationKey=12345678-abcd-abcd-abcd-12345678..."
    },
    "Console": {
      "Enable": false
    }
  },
  "EmailConfig": {
    "SenderAddress": "",
    "SenderName": "",
    "UserName": "",
    "Password": "",
    "Smtp": {
      "Host": "localhost",
      "Port": 587,
      "BypassCertVerify": false
    }
  },
  "XorKey": "<Random Key Str>",
  "ContainerProvider": {
    "Type": "Docker", // or "Kubernetes"
    "PortMappingType": "Default",
    "EnableTrafficCapture": false,
    "PublicEntry": "ctf.example.com", // or "xxx.xxx.xxx.xxx"
    "DockerConfig": {
      // optional
      "SwarmMode": false,
      "ChallengeNetwork": "",
      "Uri": "unix:///var/run/docker.sock",
      "UserName": "",
      "Password": ""
    },
    "KubernetesConfig": {
      // optional
      "Namespace": "gzctf-challenges",
      "ConfigPath": "kube-config.yaml",
      "AllowCIDR": [
        // allow the cluster CIDR for LB
        "10.0.0.0/8"
      ],
      "DNS": [
        // custom DNS to avoid cluster DNS
        "8.8.8.8",
        "223.5.5.5"
      ]
    }
  },
  "RequestLogging": false,
  "DisableRateLimit": false,
  "RegistryConfig": {
    "UserName": "",
    "Password": "",
    "ServerAddress": ""
  },
  "CaptchaConfig": {
    "Provider": "None",
    "SiteKey": "...",
    "SecretKey": "...",
    "GoogleRecaptcha": {
      "VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify",
      "RecaptchaThreshold": "0.5"
    }
  },
  "ForwardedOptions": {
    "ForwardedHeaders": 5, // a flag enum, see following link
    "ForwardLimit": 1,
    "ForwardedForHeaderName": "X-Forwarded-For",
    // use the following options to allow proxy
    "TrustedNetworks": ["10.0.0.0/8"],
    "TrustedProxies": ["10.0.0.1"]
  },
  "Kestrel": {
    "Endpoints": {
      "Web": {
        "Url": "http://*:8080"
      },
      "Prometheus": {
        "Url": "http://*:3000"
      }
    },
    "Limits": {
      "MaxResponseBufferSize": 2048,
      "MaxRequestBufferSize": 1048576,
      "MaxRequestLineSize": 8192,
      "MaxRequestHeadersTotalSize": 32768,
      "MaxRequestHeaderCount": 100,
      "MaxRequestBodySize": 27262946,
      "KeepAliveTimeout": "0.0:5:0",
      "RequestHeadersTimeout": "0.0:5:0",
      "MaxConcurrentConnections": null,
      "MaxConcurrentUpgradedConnections": null
    },
    "AddServerHeader": true,
    "AllowResponseHeaderCompression": true,
    "AllowSynchronousIO": false,
    "AllowAlternateSchemes": false,
    "DisableStringReuse": false,
    "ConfigurationLoader": null
  }
}
```

## 核心功能配置字段

### ConnectionStrings

此处配置数据库连接字符串，其中 `Database` 为必填项，`RedisCache` 为可选项。

GZCTF 使用 PostgreSQL 作为后端数据库和数据持久化，使用 Redis 作为缓存和消息队列。单实例部署的情况下 Redis 不是必须的，可以直接采用 GZCTF 的内存缓存；多实例部署的情况下，Redis 是必须的，用作共享缓存和 SignalR 的 Scale-Out 广播。

<Callout type="info">

GZCTF 仅支持 PostgreSQL 作为数据库，不支持 MySQL 等其他数据库。请在配置文件中填写正确的数据库连接字符串。

</Callout>

### Logging

此处可以配置日志级别和范围，此外，GZCTF 还支持将日志发送到 Loki 服务器。

- **LogLevel**：每个命名空间的最小日志级别。
- **Loki**：Loki 服务器的配置。

  - **Enable**：是否启用。
  - **EndpointUri**：Loki 服务器的 URI。
  - **Labels**：可选。全局日志事件标签。
  - **PropertiesAsLabels**：可选。应映射为 Loki 标签的属性列表。
  - **Credentials**：可选。将用于基本身份验证的凭据。
  - **Tenant**：可选。用于向 Loki 服务器发送日志的租户 ID。
  - **MinimumLevel**：可选。最小日志级别。

可用的日志级别：Trace, Debug, Information, Warning, Error, Critical, None。

### Telemetry

GZCTF 支持测量和分布式追踪。您可以配置您想要使用的提供商。

- **Prometheus**: Prometheus 支持。

  - **Enable**: 是否启用。
  - **Port**: 可选。Prometheus `/metrics` 的监听端口。如果配置了此项，需要额外手动配置 `Kestrel.Endpoints` 以使得服务器正常监听指定的端口。
  - **TotalNameSuffixForCounters**: 可选。是否在计数器中包含 `_total` 后缀。

- **OpenTelemetry**：将测量和追踪数据导出到 OpenTelemetry。

  - **Enable**：是否启用。
  - **Protocol**：`Grpc` 或 `HttpProtobuf`。
  - **EndpointUri**：将数据推送到的 OpenTelemetry 地址。

- **AzureMonitor**：将测量和追踪数据导出到 ApplicationInsights。

  - **Enable**：是否启用。
  - **ConnectionString**：连接字符串。

- **Console**：将追踪数据导出到控制台。

  - **Enable**：是否启用。

### EmailConfig

此处配置邮件发送相关信息，若采用邮箱注册和其他相关邮件功能，此处为必填项。

- **SenderAddress:** 发件人邮箱地址
- **SenderName:** 发件人名称
- **UserName:** SMTP 服务器用户名
- **Password:** SMTP 服务器密码
- **Smtp:** SMTP 服务器地址和端口
- **BypassCertVerify:** 是否跳过证书验证

<Callout type="info">

由于部分云服务厂家限制，可能无法采用 465 端口发送邮件。此时请尝试使用 587 端口。

</Callout>

### XorKey

此处配置加密密钥，用于加密数据库中比赛的私钥信息，可为任意长度的任意字符串。

### ContainerProvider

此处配置容器后端，为比赛动态创建容器的必填项。

- **Type:** 容器后端类型，可选 `Docker` 或 `Kubernetes`。
- **PublicEntry:** 容器后端的公网地址，用于生成比赛的访问地址，展示给参赛队伍。
- **PortMappingType:** 端口映射类型，可选 `Default` 或 `PlatformProxy`。
- **EnableTrafficCapture:** 是否开启流量捕获，仅在 `PortMappingType` 设置为 `PlatformProxy` 时可用。若开启，将会记录流量于 `/app/files/capture` 目录下。

#### Docker

- **SwarmMode:** 是否为 Swarm 模式，若为 Swarm 模式，将会使用 Swarm API 进行管理。

  <Callout type="warning">

  由于 Docker Swarm 已不是一个活跃的项目，相关安全性功能相较于 k8s 有很大距离，不推荐使用。

  </Callout>

- **Uri:** Docker API Server 地址

  - 如需使用本地 docker，请将 Uri 置空，并将 `/var/run/docker.sock` 挂载入容器对应位置
  - 如需使用外部 docker，请将 Uri 指向对应 docker API Server，**外部 API 鉴权尚未实现，不推荐此部署方式**

- **ChallengeNetwork:** 指定题目容器所在的网络，若不指定，将会使用默认网络。

- **UserName, Password:** Docker API Basic Auth 用户名和密码，可选项。

#### Kubernetes

- **Namespace:** Kubernetes 命名空间，用于创建题目实例的命名空间，默认为 `gzctf-challenges`
- **ConfigPath:** Kubernetes 配置文件路径，用于连接集群，默认为 `kube-config.yaml`
- **AllowCIDR:** 允许访问 Pod 的 CIDR 白名单
- **DNS:** 避免使用集群 DNS 的自定义 DNS 服务器列表

默认行为请将集群连接配置放入 `kube-config.yaml` 文件中，并将其挂载到 `/app` 目录下。实验功能若非了解行为请勿更改。

<Callout type="info">

请注意更改 `kube-config.yaml` 文件中的 `server` 字段，将其指向集群的 API Server 地址。集群默认地址一般为 `https://127.0.0.1:6443`，需要更改为集群实际地址。

</Callout>

<Callout type="info" emoji="👾">

为了满足网络策略，GZCTF 会在题目的 Namespace 下创建名为 `gzctf-policy` 的 NetworkPolicy，以限制访问。GZCTF 会自动检测此 NetworkPolicy 是否已经存在，若存在则不会再次创建，因此你可以通过创建或编辑此 NetworkPolicy 来自定义网络策略。

</Callout>

### RequestLogging

此处配置是否开启请求日志记录，若开启，将会在日志中输出每个请求的详细信息。此处输出不包括静态文件的请求。

### DisableRateLimit

此处配置是否开启请求频率限制，若开启，将会根据预设规则限制每个 IP 和 API 的请求频率。

### RegistryConfig

此处配置 Docker Registry 的用户名和密码，用于比赛动态创建容器时拉取镜像的验证，可选项。

- **UserName:** Docker Registry 用户名
- **Password:** Docker Registry 密码
- **ServerAddress:** Docker Registry 地址，请注意不需要包含 `https://` 前缀

<Callout type="info">

请确保密码中不包含特殊字符（如 `":@` 等，但是可以使用 `_`），否则可能导致模板注入问题，导致 Secret 创建失败。

</Callout>

### CaptchaConfig

此处配置验证码相关信息，用于注册、找回账号和登录时的验证码验证，可选项。

- **Provider:** 验证码提供商，可选 `None`、`GoogleRecaptcha` 或 `CloudflareTurnstile`
- **SiteKey:** 验证码 Sitekey
- **SecretKey:** 验证码 Secretkey

#### GoogleRecaptcha

配置 Google Recaptcha v3 的相关信息，可选项。

- **VerifyAPIAddress:** Google Recaptcha 验证 API 地址
- **RecaptchaThreshold:** Google Recaptcha 阈值，用于判断验证码是否有效

### ForwardedOptions

此处配置反向代理的相关信息，用于获取真实 IP 地址，可选项。

- **ForwardedHeaders:** 反向代理转发的标头枚举，默认请使用 `5`，详情请见 [ForwardedHeaders 枚举](https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.httpoverrides.forwardedheaders)
- **ForwardLimit:** 反向代理层数限制
- **ForwardedForHeaderName:** 反向代理 IP 地址头名称
- **TrustedNetworks:** 反向代理信任的网络列表，使用 CIDR 表示
- **TrustedProxies:** 反向代理信任的代理列表，使用 IP 地址或域名表示

<Callout type="info">

若想要忽略反向代理的信任列表，允许任意 IP 地址访问，请参考[转发 Linux 和非 IIS 反向代理的方案](https://learn.microsoft.com/zh-cn/aspnet/core/host-and-deploy/proxy-load-balancer#forward-the-scheme-for-linux-and-non-iis-reverse-proxies)，设置环境变量 `ASPNETCORE_FORWARDEDHEADERS_ENABLED` 为 `true`。

</Callout>

其他字段请参考官方文档描述：[配置 ASP.NET Core 以使用代理服务器和负载均衡器](https://learn.microsoft.com/zh-cn/aspnet/core/host-and-deploy/proxy-load-balancer) 及 [ForwardedHeadersOptions 类](https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.builder.forwardedheadersoptions)

### Kestrel

Kestrel 为 GZCTF 自带并使用的 Web 服务器。利用此配置可以自行控制 Kestrel 的行为，例如指定 HTTP 协议、修改请求大小上限等等。

- **Endpoints**: Web 服务器监听的 URL。也可以通过环境变量或启动参数来配置，具体参考 [为 ASP.NET Core Kestrel Web 服务器配置终结点](https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/servers/kestrel/endpoints)。
- 其他的可配置字段请参照官方文档中 `KestrelServerOptions` 类的属性: [KestrelServerOptions 类](https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.server.kestrel.core.kestrelserveroptions)
